This is an R Markdown
Notebook. When you execute code within the notebook, the results appear
beneath the code.
Reverse Engineer 2 Notebook
Objective: Analyze data from the Blair and Elrich campaigns for
county executive from 2018 and 2022.
###Question 1:
First thing we did is load up the sets and clean the data:
##Blair 2018 contribs:
blair_contribs_2018 <-read.csv("data2/blair_contribs_2018.csv")
blair_contribs_2018_cleaned <-blair_contribs_2018 %>%
clean_names
blair_contribs_2018_cleaned %>%
mutate(contribution_date = mdy(contribution_date))
blair_contribs_2018_cleaned
###Blair 2022 contribs
blair_contribs_2022 <-read.csv("data2/blair_contribs_2022.csv")
blair_contribs_2022_cleaned <- blair_contribs_2022 %>%
clean_names
blair_contribs_2022_cleaned %>%
mutate(contribution_date = mdy(contribution_date))
blair_contribs_2022_cleaned
###Blair 2022 expenses
blair_expenses_2022 <-read.csv("data2/blair_expenses_2022.csv")
blair_expenses_2022_cleaned <-blair_expenses_2022 %>%
clean_names
blair_expenses_2022_cleaned %>%
mutate(contribution_date = mdy(expenditure_date))
blair_expenses_2022_cleaned
###Blair 2018 expenses
blair_expenses_2018 <-read.csv("data2/blair_expenses_2018.csv")
blair_expenses_2018_cleaned <-blair_expenses_2018 %>%
clean_names()
blair_expenses_2018_cleaned %>%
mutate(contribution_date = mdy(expenditure_date))
blair_expenses_2018_cleaned
##Elrich 2018 contribs:
elrich_contribs_2018 <-read.csv("data2/elrich_contribs_2018.csv")
elrich_contribs_2018_cleaned <-elrich_contribs_2018 %>%
clean_names()
elrich_contribs_2018_cleaned %>%
mutate(contribution_date = mdy(contribution_date))
elrich_contribs_2018_cleaned
###Elrich Contribs 2022
elrich_contribs_2022 <-read.csv("data2/elrich_contribs_2022.csv")
elrich_contribs_2022_cleaned <-elrich_contribs_2022 %>%
clean_names()
elrich_contribs_2022_cleaned %>%
mutate(contribution_date = mdy(contribution_date))
elrich_contribs_2022_cleaned
###Elrich 2018
elrich_expenses_2018 <-read.csv("data2/elrich_expenses_2018.csv")
elrich_expenses_2018_cleaned <-elrich_expenses_2018 %>%
clean_names()
elrich_expenses_2018_cleaned %>%
mutate(contribution_date = mdy(expenditure_date))
elrich_expenses_2018_cleaned
###Elrich Expenses 2022
elrich_expenses_2022 <-read.csv("data2/elrich_expenses_2022.csv")
elrich_expenses_2022_cleaned <-elrich_expenses_2022 %>%
clean_names()
elrich_expenses_2022_cleaned %>%
mutate(contribution_date = mdy(expenditure_date))
elrich_expenses_2022_cleaned
##County primary election results:
dem_precincts_18 <- read.csv("data2/dem_precincts_2018.csv")
dem_precincts_22 <- read.csv("data2/dem_precincts_2022.csv")
dem_county_22 <- read.csv("data2/dem_county_2022.csv")
dem_county_18 <- read.csv("data2/dem_county_2018.csv")
###Question 1 1. How much money did David Blair and Marc Elrich fund
themselves in 2022 vs. 2018? Blair is a businessman and millionaire, so
it makes sense that he’s funding his own campaign. But how much exactly
is he putting into it, and how does it compare to the past election and
to how much Elrich’s campaign is raising?
###2022:
blair_contribs_2022_cleaned %>%
filter(contributor_name == "BLAIR DAVID THOMAS") %>%
group_by(contributor_name) %>%
summarize(total_blair = sum(contribution_amount))
elrich_contribs_2022_cleaned %>%
group_by(contributor_name) %>%
summarize(total_elrich = sum(contribution_amount)) %>%
arrange(desc(total_elrich))
###2018:
blair_contribs_2018_cleaned %>%
filter(contributor_name == "BLAIR DAVID THOMAS") %>%
group_by(contributor_name) %>%
summarize(total_blair = sum(contribution_amount))
elrich_contribs_2018_cleaned %>%
group_by(contributor_name) %>%
summarize(total_elrich = sum(contribution_amount)) %>%
arrange(desc(total_elrich))
###Question 2: Who were the top 5 contributors to Blair and Elrich in
2022? How about in 2018? What are their connections to the
candidates?
###2022
top_blair_contribs_22 <- blair_contribs_2018_cleaned %>%
mutate(contributor_name = case_when(
contributor_name == "BLAIR DAVID THOMAS" ~ "Blair David Thomas",
TRUE ~ contributor_name
)) %>%
group_by(contributor_name) %>%
summarize(total = sum(contribution_amount)) %>%
arrange(desc(total)) %>%
head(5)
top_blair_contribs_22
top_elrich_contribs_22 <- elrich_contribs_2022_cleaned %>%
group_by(contributor_name) %>%
summarize(total = sum(contribution_amount)) %>%
arrange(desc(total)) %>%
head(6)
top_elrich_contribs_22
###2018
top_blair_contribs_18 <- blair_contribs_2018_cleaned %>%
mutate(contributor_name = case_when(
contributor_name == "BLAIR DAVID THOMAS" ~ "Blair David Thomas",
TRUE ~ contributor_name
)) %>%
group_by(contributor_name) %>%
summarize(total = sum(contribution_amount)) %>%
arrange(desc(total)) %>%
head(5)
top_blair_contribs_18
top_elrich_contribs_18 <- elrich_contribs_2018_cleaned %>%
group_by(contributor_name) %>%
summarize(total = sum(contribution_amount)) %>%
arrange(desc(total)) %>%
head(6)
top_elrich_contribs_18
###Question 3: David Blair got more early/election day votes in 2022.
Elrich got more Mail-in votes in 2022. How did that compare to 2018?
People want to know how Marc Elrich won both times, first by 72 voters
in 2018 and then 32 in 2022. Where did Marc do well in the three
categories: Early voting, election day, and mail-in votes. Did this sway
the result at all?
dem_county_18_cleaned <-dem_county_18 %>%
clean_names()
dem_county_22_cleaned <-dem_county_22 %>%
clean_names()
blair <- dem_county_18_cleaned %>%
filter(candidate_name == "David Blair")
elrich <- dem_county_18_cleaned %>%
filter(candidate_name == "Marc Elrich")
blair_elrich <- bind_rows(blair, elrich)
blair_elrich
###Question 4: Which parts of the county voted for Elrich and which
voted for Blair based on precinct-level voting? Are there differences in
demographics of those areas? What about income?
\
library(sf)
Linking to GEOS 3.9.1, GDAL 3.4.3, PROJ 7.2.1; sf_use_s2() is TRUE
moco_prec_2022 <- st_read("data2/MontMD_2022/MontMD_2022.shp") %>%
st_zm(drop=TRUE)
Reading layer `MontMD_2022' from data source
`C:\Users\merca\Documents\GitHub\data_journalism_fall_2022\major_assignments\reverse_engineering\data2\MontMD_2022\MontMD_2022.shp'
using driver `ESRI Shapefile'
Simple feature collection with 261 features and 5 fields
Geometry type: MULTIPOLYGON
Dimension: XYZM
Bounding box: xmin: 1162792 ymin: 461729.6 xmax: 1344207 ymax: 614681.3
z_range: zmin: 0 zmax: 0
m_range: mmin: 0 mmax: 0
Projected CRS: NAD83 / Maryland (ftUS)
glimpse(moco_prec_2022)
Rows: 261
Columns: 6
$ NAME <chr> "MONTGOMERY PRECINCT 07-032", "MONTGOMERY PRECINCT 09-015", "MONTGOMERY PRECINCT 13-056", "M…
$ NUMBER <chr> "07-032", "09-015", "13-056", "13-016", "01-006", "04-027", "08-008", "08-016", "10-001", "0…
$ JURSCODE <chr> "MONT", "MONT", "MONT", "MONT", "MONT", "MONT", "MONT", "MONT", "MONT", "MONT", "MONT", "MON…
$ VOTESPRE <chr> "007-032", "009-015", "013-056", "013-016", "001-006", "004-027", "008-008", "008-016", "010…
$ COUNCIL <chr> "1", "3", "6", "4", "7", "6", "7", "7", "1", "6", "7", "1", "1", "7", "4", "3", "3", "2", "6…
$ geometry <MULTIPOLYGON [US_survey_foot]> MULTIPOLYGON (((1289150 485..., MULTIPOLYGON (((1251625 546..., MU…
moco_boundaries <- st_read("data2/moco_boundary.gdb")
Reading layer `CNTY_BNDY' from data source
`C:\Users\merca\Documents\GitHub\data_journalism_fall_2022\major_assignments\reverse_engineering\data2\moco_boundary.gdb'
using driver `OpenFileGDB'
Simple feature collection with 1 feature and 3 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: -77.52769 ymin: 38.93425 xmax: -76.88764 ymax: 39.35434
Geodetic CRS: WGS 84
glimpse(moco_boundaries)
Rows: 1
Columns: 4
$ NAME <chr> "MONTGOMERY COUNTY"
$ SHAPE_Length <dbl> 1.895903
$ SHAPE_Area <dbl> 0.1367927
$ SHAPE <MULTIPOLYGON [°]> MULTIPOLYGON (((-77.18523 3...
moco_boundaries %>%
ggplot() +
geom_sf() +
theme_minimal()

moco_prec_2022
Simple feature collection with 261 features and 5 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: 1162792 ymin: 461729.6 xmax: 1344207 ymax: 614681.3
Projected CRS: NAD83 / Maryland (ftUS)
First 10 features:
NAME NUMBER JURSCODE VOTESPRE COUNCIL geometry
1 MONTGOMERY PRECINCT 07-032 07-032 MONT 007-032 1 MULTIPOLYGON (((1289150 485...
2 MONTGOMERY PRECINCT 09-015 09-015 MONT 009-015 3 MULTIPOLYGON (((1251625 546...
3 MONTGOMERY PRECINCT 13-056 13-056 MONT 013-056 6 MULTIPOLYGON (((1301382 519...
4 MONTGOMERY PRECINCT 13-016 13-016 MONT 013-016 4 MULTIPOLYGON (((1298182 487...
5 MONTGOMERY PRECINCT 01-006 01-006 MONT 001-006 7 MULTIPOLYGON (((1268938 556...
6 MONTGOMERY PRECINCT 04-027 04-027 MONT 004-027 6 MULTIPOLYGON (((1280700 512...
7 MONTGOMERY PRECINCT 08-008 08-008 MONT 008-008 7 MULTIPOLYGON (((1282944 540...
8 MONTGOMERY PRECINCT 08-016 08-016 MONT 008-016 7 MULTIPOLYGON (((1295564 548...
9 MONTGOMERY PRECINCT 10-001 10-001 MONT 010-001 1 MULTIPOLYGON (((1247972 509...
10 MONTGOMERY PRECINCT 04-026 04-026 MONT 004-026 6 MULTIPOLYGON (((1285712 505...
head(moco_prec_2022)
Simple feature collection with 6 features and 5 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: 1246398 ymin: 481181.4 xmax: 1302601 ymax: 556657.3
Projected CRS: NAD83 / Maryland (ftUS)
NAME NUMBER JURSCODE VOTESPRE COUNCIL geometry
1 MONTGOMERY PRECINCT 07-032 07-032 MONT 007-032 1 MULTIPOLYGON (((1289150 485...
2 MONTGOMERY PRECINCT 09-015 09-015 MONT 009-015 3 MULTIPOLYGON (((1251625 546...
3 MONTGOMERY PRECINCT 13-056 13-056 MONT 013-056 6 MULTIPOLYGON (((1301382 519...
4 MONTGOMERY PRECINCT 13-016 13-016 MONT 013-016 4 MULTIPOLYGON (((1298182 487...
5 MONTGOMERY PRECINCT 01-006 01-006 MONT 001-006 7 MULTIPOLYGON (((1268938 556...
6 MONTGOMERY PRECINCT 04-027 04-027 MONT 004-027 6 MULTIPOLYGON (((1280700 512...
write_csv(moco_prec_2022, "data2/moco_prec_2022.csv")
moco_prec_2022 %>%
ggplot() +
geom_sf() +
theme_minimal()

moco_22_pre_results<-read.csv("data2/Moco_22_pre_results.csv")
head(moco_22_pre_results)
moco_22_pre_results_cleaned <-moco_22_pre_results %>%
clean_names()
moco_22_pre_results_cleaned
moco_22_pre_results_filtered<-moco_22_pre_results_cleaned %>%
filter(candidate_name == "David T. Blair" | candidate_name == "Marc Elrich")
moco_22_pre_results_filtered
blair_results_2022_filter<-moco_22_pre_results_filtered %>%
filter(candidate_name == "David T. Blair")
blair_results_2022_filter
blair_results_2022_filter_total <-blair_results_2022_filter%>%
mutate(total_votes_blair = early_votes + election_night_votes + mail_in_ballot_1_votes + provisional_votes + mail_in_ballot_2_votes)
blair_results_2022_filter_total
blair_results_joined_2022<- inner_join(moco_prec_2022, blair_results_2022_filter_total, by=c("VOTESPRE"="election_district_precinct"))
###Blair Map####
ggplot() +
geom_sf(data=blair_results_joined_2022, aes(fill=total_votes_blair)) +
scale_fill_viridis_b(option="magma")+
theme_minimal()

####Elirich map####
moco_22_pre_results_filtered_elrich <-moco_22_pre_results_cleaned %>%
filter(candidate_name == "Marc Elrich")
moco_22_pre_results_filtered_elrich
elrich_22_filtered_total <-moco_22_pre_results_filtered_elrich%>%
mutate(total_votes_elrich = early_votes + election_night_votes + mail_in_ballot_1_votes + provisional_votes + mail_in_ballot_2_votes)
elrich_22_filtered_total
elrich_results_joined_2022_map<- inner_join(moco_prec_2022, elrich_22_filtered_total, by=c("VOTESPRE"="election_district_precinct"))
ggplot() +
geom_sf(data=elrich_results_joined_2022_map, aes(fill=total_votes_elrich)) +
scale_fill_viridis_b(option="magma")+
theme_minimal()

###percentage_change***
blair_results_2022_filter_total
elrich_22_filtered_total
both_joined_2022<- left_join(blair_results_2022_filter_total, elrich_22_filtered_total, by=c("county"="county"))
both_joined_2022
both_joined_mutated<-both_joined_2022 %>%
mutate(difference = total_votes_elrich-total_votes_blair)
both_joined_mutated
NA
both_joined_map<- inner_join(moco_prec_2022, both_joined_mutated, by=c("VOTESPRE"="election_district_precinct.x"))
ggplot() +
geom_sf(data=both_joined_map, aes(fill=difference)) +
scale_fill_viridis_b(option="magma")+
theme_minimal()

library(ggplot2)
ggplot(results_joined_2022)+
geom_map(aes(map_id = region))+
expand_limits()
###Question 5: Where did David Blair and Marc Elrich spend their
money on campaign finance resources? Ie: Meta advertisements, yard
signs, TV, consulting? This would be interesting to know since Blair
made a very big concerted effort to build his profile during the
campaign while Elrich relied on incumbency and mainly TV ads to help
him.
blair_expenses_2022_cleaned %>%
group_by(expense_category) %>%
summarize(total_category = sum(amount)) %>%
arrange(desc(total_category))
#spent nearly $3.1 mil in 2022 ... top 3 are Media, Salarties and Direct Mail by Mail House (R)
#dive into media
blair_expenses_2022_cleaned %>%
filter(expense_category == "Media") %>%
group_by(expense_purpose) %>%
summarize(total_category = sum(amount)) %>%
arrange(desc(total_category))
Spent 1773.00 on online advertising
elrich_expenses_2022_cleaned %>%
group_by(expense_category) %>%
summarize(total_category = sum(amount)) %>%
arrange(desc(total_category))
Elrich spent $528393.29 on media which is significantly less than
Blair
elrich_expenses_2022_cleaned %>%
filter(expense_category == "Media") %>%
group_by(expense_purpose) %>%
summarize(total_category = sum(amount)) %>%
arrange(desc(total_category))
#Elrich spent 32K on consulting fees.
This is what I wrote for No. 5 “There are signifant differences in
spending between Elrich and Blair here and it shows how the capital on
hand can really influence the means a candidate has to win or lose a
race. Elrich in 2022 went all-in on TV spending. Blair spent a lot more
in 2018 as well.”
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpUaGlzIGlzIGFuIFtSIE1hcmtkb3duXShodHRwOi8vcm1hcmtkb3duLnJzdHVkaW8uY29tKSBOb3RlYm9vay4gV2hlbiB5b3UgZXhlY3V0ZSBjb2RlIHdpdGhpbiB0aGUgbm90ZWJvb2ssIHRoZSByZXN1bHRzIGFwcGVhciBiZW5lYXRoIHRoZSBjb2RlLiANCg0KDQpSZXZlcnNlIEVuZ2luZWVyIDIgTm90ZWJvb2sNCg0KT2JqZWN0aXZlOiBBbmFseXplIGRhdGEgZnJvbSB0aGUgQmxhaXIgYW5kIEVscmljaCBjYW1wYWlnbnMgZm9yIGNvdW50eSBleGVjdXRpdmUgZnJvbSAyMDE4IGFuZCAyMDIyLg0KDQojIyNRdWVzdGlvbiAxOg0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmBgYA0KDQoNCmBgYHtyIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0V9DQpvcHRpb25zKHNjaXBlbj05OTkpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeShqYW5pdG9yKQ0KDQpgYGANCg0KDQoNCkZpcnN0IHRoaW5nIHdlIGRpZCBpcyBsb2FkIHVwIHRoZSBzZXRzIGFuZCBjbGVhbiB0aGUgZGF0YToNCg0KIyNCbGFpciAyMDE4IGNvbnRyaWJzOg0KDQpgYGB7cn0NCmJsYWlyX2NvbnRyaWJzXzIwMTggPC1yZWFkLmNzdigiZGF0YTIvYmxhaXJfY29udHJpYnNfMjAxOC5jc3YiKQ0KYGBgDQoNCmBgYHtyfQ0KYmxhaXJfY29udHJpYnNfMjAxOF9jbGVhbmVkIDwtYmxhaXJfY29udHJpYnNfMjAxOCAlPiUgDQpjbGVhbl9uYW1lcyAgDQogIA0KICANCmJsYWlyX2NvbnRyaWJzXzIwMThfY2xlYW5lZCAlPiUgICANCm11dGF0ZShjb250cmlidXRpb25fZGF0ZSA9IG1keShjb250cmlidXRpb25fZGF0ZSkpIA0KYmxhaXJfY29udHJpYnNfMjAxOF9jbGVhbmVkDQpgYGANCg0KDQojIyNCbGFpciAyMDIyIGNvbnRyaWJzDQoNCmBgYHtyfQ0KYmxhaXJfY29udHJpYnNfMjAyMiA8LXJlYWQuY3N2KCJkYXRhMi9ibGFpcl9jb250cmlic18yMDIyLmNzdiIpDQpgYGANCg0KYGBge3J9DQpibGFpcl9jb250cmlic18yMDIyX2NsZWFuZWQgPC0gYmxhaXJfY29udHJpYnNfMjAyMiAlPiUgDQpjbGVhbl9uYW1lcyANCmBgYCAgDQogIA0KYGBge3J9ICANCmJsYWlyX2NvbnRyaWJzXzIwMjJfY2xlYW5lZCAlPiUgDQptdXRhdGUoY29udHJpYnV0aW9uX2RhdGUgPSBtZHkoY29udHJpYnV0aW9uX2RhdGUpKSANCg0KYmxhaXJfY29udHJpYnNfMjAyMl9jbGVhbmVkDQpgYGANCg0KIyMjQmxhaXIgMjAyMiBleHBlbnNlcw0KDQpgYGB7cn0NCmJsYWlyX2V4cGVuc2VzXzIwMjIgPC1yZWFkLmNzdigiZGF0YTIvYmxhaXJfZXhwZW5zZXNfMjAyMi5jc3YiKQ0KYGBgDQoNCmBgYHtyfQ0KYmxhaXJfZXhwZW5zZXNfMjAyMl9jbGVhbmVkIDwtYmxhaXJfZXhwZW5zZXNfMjAyMiAlPiUgDQogIGNsZWFuX25hbWVzIA0KYGBgDQoNCmBgYHtyfQ0KYmxhaXJfZXhwZW5zZXNfMjAyMl9jbGVhbmVkICU+JSANCm11dGF0ZShjb250cmlidXRpb25fZGF0ZSA9IG1keShleHBlbmRpdHVyZV9kYXRlKSkgDQoNCmJsYWlyX2V4cGVuc2VzXzIwMjJfY2xlYW5lZA0KYGBgDQoNCiMjI0JsYWlyIDIwMTggZXhwZW5zZXMNCg0KDQpgYGB7cn0NCmJsYWlyX2V4cGVuc2VzXzIwMTggPC1yZWFkLmNzdigiZGF0YTIvYmxhaXJfZXhwZW5zZXNfMjAxOC5jc3YiKQ0KYGBgDQoNCmBgYHtyfQ0KYmxhaXJfZXhwZW5zZXNfMjAxOF9jbGVhbmVkIDwtYmxhaXJfZXhwZW5zZXNfMjAxOCAlPiUgDQogIGNsZWFuX25hbWVzKCkNCmBgYA0KDQpgYGB7cn0NCmJsYWlyX2V4cGVuc2VzXzIwMThfY2xlYW5lZCAlPiUgDQogIG11dGF0ZShjb250cmlidXRpb25fZGF0ZSA9IG1keShleHBlbmRpdHVyZV9kYXRlKSkgDQpibGFpcl9leHBlbnNlc18yMDE4X2NsZWFuZWQgDQpgYGANCg0KIyNFbHJpY2ggMjAxOCBjb250cmliczoNCg0KYGBge3J9DQplbHJpY2hfY29udHJpYnNfMjAxOCA8LXJlYWQuY3N2KCJkYXRhMi9lbHJpY2hfY29udHJpYnNfMjAxOC5jc3YiKQ0KYGBgDQoNCmBgYHtyfQ0KZWxyaWNoX2NvbnRyaWJzXzIwMThfY2xlYW5lZCA8LWVscmljaF9jb250cmlic18yMDE4ICU+JSANCiAgY2xlYW5fbmFtZXMoKQ0KYGBgDQoNCmBgYHtyfQ0KZWxyaWNoX2NvbnRyaWJzXzIwMThfY2xlYW5lZCAlPiUgDQogIG11dGF0ZShjb250cmlidXRpb25fZGF0ZSA9IG1keShjb250cmlidXRpb25fZGF0ZSkpIA0KDQplbHJpY2hfY29udHJpYnNfMjAxOF9jbGVhbmVkDQpgYGANCg0KIyMjRWxyaWNoIENvbnRyaWJzIDIwMjINCg0KYGBge3J9DQplbHJpY2hfY29udHJpYnNfMjAyMiA8LXJlYWQuY3N2KCJkYXRhMi9lbHJpY2hfY29udHJpYnNfMjAyMi5jc3YiKQ0KYGBgDQoNCmBgYHtyfQ0KZWxyaWNoX2NvbnRyaWJzXzIwMjJfY2xlYW5lZCA8LWVscmljaF9jb250cmlic18yMDIyICU+JQ0KICBjbGVhbl9uYW1lcygpDQpgYGANCg0KYGBge3J9DQplbHJpY2hfY29udHJpYnNfMjAyMl9jbGVhbmVkICU+JSANCiAgbXV0YXRlKGNvbnRyaWJ1dGlvbl9kYXRlID0gbWR5KGNvbnRyaWJ1dGlvbl9kYXRlKSkgDQoNCmVscmljaF9jb250cmlic18yMDIyX2NsZWFuZWQNCmBgYA0KDQojIyNFbHJpY2ggMjAxOA0KDQpgYGB7cn0NCmVscmljaF9leHBlbnNlc18yMDE4IDwtcmVhZC5jc3YoImRhdGEyL2VscmljaF9leHBlbnNlc18yMDE4LmNzdiIpDQpgYGANCg0KYGBge3J9DQplbHJpY2hfZXhwZW5zZXNfMjAxOF9jbGVhbmVkIDwtZWxyaWNoX2V4cGVuc2VzXzIwMTggJT4lIA0KICBjbGVhbl9uYW1lcygpDQpgYGANCg0KYGBge3J9DQplbHJpY2hfZXhwZW5zZXNfMjAxOF9jbGVhbmVkICU+JSANCiAgICBtdXRhdGUoY29udHJpYnV0aW9uX2RhdGUgPSBtZHkoZXhwZW5kaXR1cmVfZGF0ZSkpIA0KZWxyaWNoX2V4cGVuc2VzXzIwMThfY2xlYW5lZA0KYGBgDQojIyNFbHJpY2ggRXhwZW5zZXMgMjAyMg0KDQpgYGB7cn0NCmVscmljaF9leHBlbnNlc18yMDIyIDwtcmVhZC5jc3YoImRhdGEyL2VscmljaF9leHBlbnNlc18yMDIyLmNzdiIpDQpgYGANCg0KYGBge3J9DQplbHJpY2hfZXhwZW5zZXNfMjAyMl9jbGVhbmVkIDwtZWxyaWNoX2V4cGVuc2VzXzIwMjIgJT4lIA0KICBjbGVhbl9uYW1lcygpDQpgYGANCg0KYGBge3J9DQplbHJpY2hfZXhwZW5zZXNfMjAyMl9jbGVhbmVkICU+JSANCiAgbXV0YXRlKGNvbnRyaWJ1dGlvbl9kYXRlID0gbWR5KGV4cGVuZGl0dXJlX2RhdGUpKSANCmVscmljaF9leHBlbnNlc18yMDIyX2NsZWFuZWQNCmBgYA0KDQoNCiMjQ291bnR5IHByaW1hcnkgZWxlY3Rpb24gcmVzdWx0czoNCg0KDQoNCmBgYHtyfQ0KZGVtX3ByZWNpbmN0c18xOCA8LSByZWFkLmNzdigiZGF0YTIvZGVtX3ByZWNpbmN0c18yMDE4LmNzdiIpDQpgYGANCg0KYGBge3J9DQpkZW1fcHJlY2luY3RzXzIyIDwtIHJlYWQuY3N2KCJkYXRhMi9kZW1fcHJlY2luY3RzXzIwMjIuY3N2IikNCmBgYA0KDQoNCg0KDQoNCmBgYHtyfQ0KZGVtX2NvdW50eV8yMiA8LSByZWFkLmNzdigiZGF0YTIvZGVtX2NvdW50eV8yMDIyLmNzdiIpDQpgYGANCg0KYGBge3J9DQpkZW1fY291bnR5XzE4IDwtIHJlYWQuY3N2KCJkYXRhMi9kZW1fY291bnR5XzIwMTguY3N2IikNCmBgYA0KDQoNCg0KDQojIyNRdWVzdGlvbiAxIDEuIEhvdyBtdWNoIG1vbmV5IGRpZCBEYXZpZCBCbGFpciBhbmQgTWFyYyBFbHJpY2ggZnVuZCB0aGVtc2VsdmVzIGluIDIwMjIgdnMuIDIwMTg/IEJsYWlyIGlzIGEgYnVzaW5lc3NtYW4gYW5kIG1pbGxpb25haXJlLCBzbyBpdCBtYWtlcyBzZW5zZSB0aGF0IGhl4oCZcyBmdW5kaW5nIGhpcyBvd24gY2FtcGFpZ24uIEJ1dCBob3cgbXVjaCBleGFjdGx5IGlzIGhlIHB1dHRpbmcgaW50byBpdCwgYW5kIGhvdyBkb2VzIGl0IGNvbXBhcmUgdG8gdGhlIHBhc3QgZWxlY3Rpb24gYW5kIHRvIGhvdyBtdWNoIEVscmljaOKAmXMgY2FtcGFpZ24gaXMgcmFpc2luZz8NCg0KIyMjMjAyMjoNCg0KYGBge3J9DQpibGFpcl9jb250cmlic18yMDIyX2NsZWFuZWQgJT4lDQpmaWx0ZXIoY29udHJpYnV0b3JfbmFtZSA9PSAiQkxBSVIgIERBVklEICBUSE9NQVMiKSAlPiUNCmdyb3VwX2J5KGNvbnRyaWJ1dG9yX25hbWUpICU+JQ0Kc3VtbWFyaXplKHRvdGFsX2JsYWlyID0gc3VtKGNvbnRyaWJ1dGlvbl9hbW91bnQpKQ0KYGBgDQoNCmBgYHtyfQ0KZWxyaWNoX2NvbnRyaWJzXzIwMjJfY2xlYW5lZCAlPiUNCmdyb3VwX2J5KGNvbnRyaWJ1dG9yX25hbWUpICU+JQ0Kc3VtbWFyaXplKHRvdGFsX2VscmljaCA9IHN1bShjb250cmlidXRpb25fYW1vdW50KSkgJT4lDQphcnJhbmdlKGRlc2ModG90YWxfZWxyaWNoKSkNCmBgYA0KIyMjMjAxODoNCg0KYGBge3J9DQpibGFpcl9jb250cmlic18yMDE4X2NsZWFuZWQgJT4lDQpmaWx0ZXIoY29udHJpYnV0b3JfbmFtZSA9PSAiQkxBSVIgIERBVklEICBUSE9NQVMiKSAlPiUNCmdyb3VwX2J5KGNvbnRyaWJ1dG9yX25hbWUpICU+JQ0Kc3VtbWFyaXplKHRvdGFsX2JsYWlyID0gc3VtKGNvbnRyaWJ1dGlvbl9hbW91bnQpKQ0KYGBgDQpgYGB7cn0NCmVscmljaF9jb250cmlic18yMDE4X2NsZWFuZWQgJT4lDQpncm91cF9ieShjb250cmlidXRvcl9uYW1lKSAlPiUNCnN1bW1hcml6ZSh0b3RhbF9lbHJpY2ggPSBzdW0oY29udHJpYnV0aW9uX2Ftb3VudCkpICU+JQ0KYXJyYW5nZShkZXNjKHRvdGFsX2VscmljaCkpDQpgYGANCiANCiMjI1F1ZXN0aW9uIDI6IFdobyB3ZXJlIHRoZSB0b3AgNSBjb250cmlidXRvcnMgdG8gQmxhaXIgYW5kIEVscmljaCBpbiAyMDIyPyBIb3cgYWJvdXQgaW4gMjAxOD8gV2hhdCBhcmUgdGhlaXIgY29ubmVjdGlvbnMgdG8gdGhlIGNhbmRpZGF0ZXM/DQoNCg0KIyMjMjAyMg0KYGBge3J9DQp0b3BfYmxhaXJfY29udHJpYnNfMjIgPC0gYmxhaXJfY29udHJpYnNfMjAxOF9jbGVhbmVkICU+JQ0KICBtdXRhdGUoY29udHJpYnV0b3JfbmFtZSA9IGNhc2Vfd2hlbigNCiAgICBjb250cmlidXRvcl9uYW1lID09ICJCTEFJUiAgREFWSUQgIFRIT01BUyIgfiAiQmxhaXIgIERhdmlkICBUaG9tYXMiLA0KICAgIFRSVUUgfiBjb250cmlidXRvcl9uYW1lDQogICkpICU+JQ0KICBncm91cF9ieShjb250cmlidXRvcl9uYW1lKSAlPiUNCiAgc3VtbWFyaXplKHRvdGFsID0gc3VtKGNvbnRyaWJ1dGlvbl9hbW91bnQpKSAlPiUNCiAgYXJyYW5nZShkZXNjKHRvdGFsKSkgJT4lDQogIGhlYWQoNSkNCnRvcF9ibGFpcl9jb250cmlic18yMg0KYGBgDQoNCmBgYHtyfQ0KdG9wX2VscmljaF9jb250cmlic18yMiA8LSBlbHJpY2hfY29udHJpYnNfMjAyMl9jbGVhbmVkICU+JQ0KICBncm91cF9ieShjb250cmlidXRvcl9uYW1lKSAlPiUNCiAgc3VtbWFyaXplKHRvdGFsID0gc3VtKGNvbnRyaWJ1dGlvbl9hbW91bnQpKSAlPiUNCiAgYXJyYW5nZShkZXNjKHRvdGFsKSkgJT4lDQogIGhlYWQoNikNCnRvcF9lbHJpY2hfY29udHJpYnNfMjINCmBgYA0KDQojIyMyMDE4DQoNCmBgYHtyfQ0KdG9wX2JsYWlyX2NvbnRyaWJzXzE4IDwtIGJsYWlyX2NvbnRyaWJzXzIwMThfY2xlYW5lZCAlPiUNCiAgbXV0YXRlKGNvbnRyaWJ1dG9yX25hbWUgPSBjYXNlX3doZW4oDQogICAgY29udHJpYnV0b3JfbmFtZSA9PSAiQkxBSVIgIERBVklEICBUSE9NQVMiIH4gIkJsYWlyICBEYXZpZCAgVGhvbWFzIiwNCiAgICBUUlVFIH4gY29udHJpYnV0b3JfbmFtZQ0KICApKSAlPiUNCiAgZ3JvdXBfYnkoY29udHJpYnV0b3JfbmFtZSkgJT4lDQogIHN1bW1hcml6ZSh0b3RhbCA9IHN1bShjb250cmlidXRpb25fYW1vdW50KSkgJT4lDQogIGFycmFuZ2UoZGVzYyh0b3RhbCkpICU+JQ0KICBoZWFkKDUpDQp0b3BfYmxhaXJfY29udHJpYnNfMTgNCmBgYA0KDQpgYGB7cn0NCnRvcF9lbHJpY2hfY29udHJpYnNfMTggPC0gZWxyaWNoX2NvbnRyaWJzXzIwMThfY2xlYW5lZCAlPiUNCiAgZ3JvdXBfYnkoY29udHJpYnV0b3JfbmFtZSkgJT4lDQogIHN1bW1hcml6ZSh0b3RhbCA9IHN1bShjb250cmlidXRpb25fYW1vdW50KSkgJT4lDQogIGFycmFuZ2UoZGVzYyh0b3RhbCkpICU+JQ0KICBoZWFkKDYpDQp0b3BfZWxyaWNoX2NvbnRyaWJzXzE4DQpgYGANCg0KIyMjUXVlc3Rpb24gMzogRGF2aWQgQmxhaXIgZ290IG1vcmUgZWFybHkvZWxlY3Rpb24gZGF5IHZvdGVzIGluIDIwMjIuIEVscmljaCBnb3QgbW9yZSBNYWlsLWluIHZvdGVzIGluIDIwMjIuIEhvdyBkaWQgdGhhdCBjb21wYXJlIHRvIDIwMTg/IFBlb3BsZSB3YW50IHRvIGtub3cgaG93IE1hcmMgRWxyaWNoIHdvbiBib3RoIHRpbWVzLCBmaXJzdCBieSA3MiB2b3RlcnMgaW4gMjAxOCBhbmQgdGhlbiAzMiBpbiAyMDIyLiBXaGVyZSBkaWQgTWFyYyBkbyB3ZWxsIGluIHRoZSB0aHJlZSBjYXRlZ29yaWVzOiBFYXJseSB2b3RpbmcsIGVsZWN0aW9uIGRheSwgYW5kIG1haWwtaW4gdm90ZXMuIERpZCB0aGlzIHN3YXkgdGhlIHJlc3VsdCBhdCBhbGw/DQoNCmBgYHtyfQ0KZGVtX2NvdW50eV8xOF9jbGVhbmVkIDwtZGVtX2NvdW50eV8xOCAlPiUgDQogIGNsZWFuX25hbWVzKCkNCmBgYA0KDQoNCmBgYHtyfQ0KZGVtX2NvdW50eV8yMl9jbGVhbmVkIDwtZGVtX2NvdW50eV8yMiAlPiUgDQogIGNsZWFuX25hbWVzKCkNCmBgYA0KDQoNCg0KYGBge3J9DQoNCmJsYWlyIDwtIGRlbV9jb3VudHlfMThfY2xlYW5lZCAlPiUNCmZpbHRlcihjYW5kaWRhdGVfbmFtZSA9PSAiRGF2aWQgQmxhaXIiKQ0KZWxyaWNoIDwtICBkZW1fY291bnR5XzE4X2NsZWFuZWQgJT4lDQogIGZpbHRlcihjYW5kaWRhdGVfbmFtZSA9PSAiTWFyYyBFbHJpY2giKQ0KYmxhaXJfZWxyaWNoIDwtICBiaW5kX3Jvd3MoYmxhaXIsIGVscmljaCkNCmJsYWlyX2VscmljaA0KYGBgDQoNCg0KDQoNCg0KIyMjUXVlc3Rpb24gNDogV2hpY2ggcGFydHMgb2YgdGhlIGNvdW50eSB2b3RlZCBmb3IgRWxyaWNoIGFuZCB3aGljaCB2b3RlZCBmb3IgQmxhaXIgYmFzZWQgb24gcHJlY2luY3QtbGV2ZWwgdm90aW5nPyBBcmUgdGhlcmUgZGlmZmVyZW5jZXMgaW4gZGVtb2dyYXBoaWNzIG9mIHRob3NlIGFyZWFzPyBXaGF0IGFib3V0IGluY29tZT8gDQoNClxcDQoNCmBgYHtyfQ0KbGlicmFyeShzZikNCmBgYA0KDQpgYGB7cn0NCm1vY29fcHJlY18yMDIyIDwtIHN0X3JlYWQoImRhdGEyL01vbnRNRF8yMDIyL01vbnRNRF8yMDIyLnNocCIpICU+JSANCiAgc3Rfem0oZHJvcD1UUlVFKQ0KZ2xpbXBzZShtb2NvX3ByZWNfMjAyMikNCmBgYA0KDQoNCg0KDQpgYGB7cn0NCm1vY29fYm91bmRhcmllcyA8LSBzdF9yZWFkKCJkYXRhMi9tb2NvX2JvdW5kYXJ5LmdkYiIpDQoNCmdsaW1wc2UobW9jb19ib3VuZGFyaWVzKQ0KYGBgDQoNCg0KYGBge3J9DQptb2NvX2JvdW5kYXJpZXMgJT4lDQogIGdncGxvdCgpICsNCiAgZ2VvbV9zZigpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCmBgYHtyfQ0KbW9jb19wcmVjXzIwMjINCmhlYWQobW9jb19wcmVjXzIwMjIpDQpgYGANCmBgYHtyfQ0Kd3JpdGVfY3N2KG1vY29fcHJlY18yMDIyLCAiZGF0YTIvbW9jb19wcmVjXzIwMjIuY3N2IikNCmBgYA0KDQpgYGB7cn0NCm1vY29fcHJlY18yMDIyICU+JQ0KICBnZ3Bsb3QoKSArDQogIGdlb21fc2YoKSArDQogIHRoZW1lX21pbmltYWwoKQ0KYGBgDQpgYGB7cn0NCm1vY29fMjJfcHJlX3Jlc3VsdHM8LXJlYWQuY3N2KCJkYXRhMi9Nb2NvXzIyX3ByZV9yZXN1bHRzLmNzdiIpDQpoZWFkKG1vY29fMjJfcHJlX3Jlc3VsdHMpDQpgYGANCg0KYGBge3J9DQptb2NvXzIyX3ByZV9yZXN1bHRzX2NsZWFuZWQgPC1tb2NvXzIyX3ByZV9yZXN1bHRzICU+JSANCiAgY2xlYW5fbmFtZXMoKQ0KbW9jb18yMl9wcmVfcmVzdWx0c19jbGVhbmVkDQpgYGANCg0KDQoNCg0KYGBge3J9DQptb2NvXzIyX3ByZV9yZXN1bHRzX2ZpbHRlcmVkPC1tb2NvXzIyX3ByZV9yZXN1bHRzX2NsZWFuZWQgJT4lDQpmaWx0ZXIoY2FuZGlkYXRlX25hbWUgPT0gIkRhdmlkIFQuIEJsYWlyIiB8IGNhbmRpZGF0ZV9uYW1lID09ICJNYXJjIEVscmljaCIpDQptb2NvXzIyX3ByZV9yZXN1bHRzX2ZpbHRlcmVkDQpgYGANCmBgYHtyfQ0KYmxhaXJfcmVzdWx0c18yMDIyX2ZpbHRlcjwtbW9jb18yMl9wcmVfcmVzdWx0c19maWx0ZXJlZCAlPiUgDQogIGZpbHRlcihjYW5kaWRhdGVfbmFtZSA9PSAiRGF2aWQgVC4gQmxhaXIiKQ0KYmxhaXJfcmVzdWx0c18yMDIyX2ZpbHRlcg0KYGBgDQoNCg0KDQoNCmBgYHtyfQ0KYmxhaXJfcmVzdWx0c18yMDIyX2ZpbHRlcl90b3RhbCA8LWJsYWlyX3Jlc3VsdHNfMjAyMl9maWx0ZXIlPiUgDQogIG11dGF0ZSh0b3RhbF92b3Rlc19ibGFpciA9IGVhcmx5X3ZvdGVzICsgZWxlY3Rpb25fbmlnaHRfdm90ZXMgKyBtYWlsX2luX2JhbGxvdF8xX3ZvdGVzICsgcHJvdmlzaW9uYWxfdm90ZXMgKyBtYWlsX2luX2JhbGxvdF8yX3ZvdGVzKQ0KYmxhaXJfcmVzdWx0c18yMDIyX2ZpbHRlcl90b3RhbA0KYGBgDQpgYGB7cn0NCmJsYWlyX3Jlc3VsdHNfam9pbmVkXzIwMjI8LSBpbm5lcl9qb2luKG1vY29fcHJlY18yMDIyLCBibGFpcl9yZXN1bHRzXzIwMjJfZmlsdGVyX3RvdGFsLCBieT1jKCJWT1RFU1BSRSI9ImVsZWN0aW9uX2Rpc3RyaWN0X3ByZWNpbmN0IikpDQpgYGANCg0KDQoNCg0KIyMjQmxhaXIgTWFwIyMjIw0KYGBge3J9DQpnZ3Bsb3QoKSArDQogIGdlb21fc2YoZGF0YT1ibGFpcl9yZXN1bHRzX2pvaW5lZF8yMDIyLCBhZXMoZmlsbD10b3RhbF92b3Rlc19ibGFpcikpICsNCiAgc2NhbGVfZmlsbF92aXJpZGlzX2Iob3B0aW9uPSJtYWdtYSIpKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KIyMjI0VsaXJpY2ggbWFwIyMjIw0KYGBge3J9DQptb2NvXzIyX3ByZV9yZXN1bHRzX2ZpbHRlcmVkX2VscmljaCA8LW1vY29fMjJfcHJlX3Jlc3VsdHNfY2xlYW5lZCAlPiUNCmZpbHRlcihjYW5kaWRhdGVfbmFtZSA9PSAiTWFyYyBFbHJpY2giKQ0KbW9jb18yMl9wcmVfcmVzdWx0c19maWx0ZXJlZF9lbHJpY2gNCmBgYA0KYGBge3J9DQplbHJpY2hfMjJfZmlsdGVyZWRfdG90YWwgPC1tb2NvXzIyX3ByZV9yZXN1bHRzX2ZpbHRlcmVkX2VscmljaCU+JSANCiAgbXV0YXRlKHRvdGFsX3ZvdGVzX2VscmljaCA9IGVhcmx5X3ZvdGVzICsgZWxlY3Rpb25fbmlnaHRfdm90ZXMgKyBtYWlsX2luX2JhbGxvdF8xX3ZvdGVzICsgcHJvdmlzaW9uYWxfdm90ZXMgKyBtYWlsX2luX2JhbGxvdF8yX3ZvdGVzKQ0KZWxyaWNoXzIyX2ZpbHRlcmVkX3RvdGFsDQpgYGANCmBgYHtyfQ0KZWxyaWNoX3Jlc3VsdHNfam9pbmVkXzIwMjJfbWFwPC0gaW5uZXJfam9pbihtb2NvX3ByZWNfMjAyMiwgZWxyaWNoXzIyX2ZpbHRlcmVkX3RvdGFsLCBieT1jKCJWT1RFU1BSRSI9ImVsZWN0aW9uX2Rpc3RyaWN0X3ByZWNpbmN0IikpDQpgYGANCg0KYGBge3J9DQpnZ3Bsb3QoKSArDQogIGdlb21fc2YoZGF0YT1lbHJpY2hfcmVzdWx0c19qb2luZWRfMjAyMl9tYXAsIGFlcyhmaWxsPXRvdGFsX3ZvdGVzX2VscmljaCkpICsNCiAgc2NhbGVfZmlsbF92aXJpZGlzX2Iob3B0aW9uPSJtYWdtYSIpKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KIyMjcGVyY2VudGFnZV9jaGFuZ2UqKioNCmBgYHtyfQ0KYmxhaXJfcmVzdWx0c18yMDIyX2ZpbHRlcl90b3RhbA0KYGBgDQoNCmBgYHtyfQ0KZWxyaWNoXzIyX2ZpbHRlcmVkX3RvdGFsDQpgYGANCg0KDQpgYGB7cn0NCmJvdGhfam9pbmVkXzIwMjI8LSBsZWZ0X2pvaW4oYmxhaXJfcmVzdWx0c18yMDIyX2ZpbHRlcl90b3RhbCwgZWxyaWNoXzIyX2ZpbHRlcmVkX3RvdGFsLCBieT1jKCJjb3VudHkiPSJjb3VudHkiKSkNCmBgYA0KDQpgYGB7cn0NCmJvdGhfam9pbmVkXzIwMjINCmBgYA0KYGBge3J9DQpib3RoX2pvaW5lZF9tdXRhdGVkPC1ib3RoX2pvaW5lZF8yMDIyICU+JSANCiAgbXV0YXRlKGRpZmZlcmVuY2UgPSB0b3RhbF92b3Rlc19lbHJpY2gtdG90YWxfdm90ZXNfYmxhaXIpDQpib3RoX2pvaW5lZF9tdXRhdGVkDQoNCmBgYA0KYGBge3J9DQpib3RoX2pvaW5lZF9tYXA8LSBpbm5lcl9qb2luKG1vY29fcHJlY18yMDIyLCBib3RoX2pvaW5lZF9tdXRhdGVkLCBieT1jKCJWT1RFU1BSRSI9ImVsZWN0aW9uX2Rpc3RyaWN0X3ByZWNpbmN0LngiKSkNCmBgYA0KDQpgYGB7cn0NCmdncGxvdCgpICsNCiAgZ2VvbV9zZihkYXRhPWJvdGhfam9pbmVkX21hcCwgYWVzKGZpbGw9ZGlmZmVyZW5jZSkpICsNCiAgc2NhbGVfZmlsbF92aXJpZGlzX2Iob3B0aW9uPSJtYWdtYSIpKw0KICB0aGVtZV9taW5pbWFsKCkNCmBgYA0KDQoNCg0KDQoNCg0KDQoNCmBgYHtyfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KYGBgDQoNCmBgYHtyfQ0KZ2dwbG90KHJlc3VsdHNfam9pbmVkXzIwMjIpKw0KICBnZW9tX21hcChhZXMobWFwX2lkID0gcmVnaW9uKSkrDQogIGV4cGFuZF9saW1pdHMoKQ0KYGBgDQoNCg0KIyMjUXVlc3Rpb24gNTogV2hlcmUgZGlkIERhdmlkIEJsYWlyIGFuZCBNYXJjIEVscmljaCBzcGVuZCB0aGVpciBtb25leSBvbiBjYW1wYWlnbiBmaW5hbmNlIHJlc291cmNlcz8gSWU6IE1ldGEgYWR2ZXJ0aXNlbWVudHMsIHlhcmQgc2lnbnMsIFRWLCBjb25zdWx0aW5nPyBUaGlzIHdvdWxkIGJlIGludGVyZXN0aW5nIHRvIGtub3cgc2luY2UgQmxhaXIgbWFkZSBhIHZlcnkgYmlnIGNvbmNlcnRlZCBlZmZvcnQgdG8gYnVpbGQgaGlzIHByb2ZpbGUgZHVyaW5nIHRoZSBjYW1wYWlnbiB3aGlsZSBFbHJpY2ggcmVsaWVkIG9uIGluY3VtYmVuY3kgYW5kIG1haW5seSBUViBhZHMgdG8gaGVscCBoaW0uIA0KDQoNCmBgYHtyfQ0KYmxhaXJfZXhwZW5zZXNfMjAyMl9jbGVhbmVkICU+JQ0KZ3JvdXBfYnkoZXhwZW5zZV9jYXRlZ29yeSkgJT4lDQpzdW1tYXJpemUodG90YWxfY2F0ZWdvcnkgPSBzdW0oYW1vdW50KSkgJT4lDQphcnJhbmdlKGRlc2ModG90YWxfY2F0ZWdvcnkpKQ0KI3NwZW50IG5lYXJseSAkMy4xIG1pbCBpbiAyMDIyIC4uLiB0b3AgMyBhcmUgTWVkaWEsIFNhbGFydGllcyBhbmQgRGlyZWN0IE1haWwgYnkgTWFpbCBIb3VzZSAoUikNCmBgYA0KI2RpdmUgaW50byBtZWRpYQ0KYGBge3J9DQpibGFpcl9leHBlbnNlc18yMDIyX2NsZWFuZWQgJT4lDQpmaWx0ZXIoZXhwZW5zZV9jYXRlZ29yeSA9PSAiTWVkaWEiKSAlPiUNCmdyb3VwX2J5KGV4cGVuc2VfcHVycG9zZSkgJT4lDQpzdW1tYXJpemUodG90YWxfY2F0ZWdvcnkgPSBzdW0oYW1vdW50KSkgJT4lDQphcnJhbmdlKGRlc2ModG90YWxfY2F0ZWdvcnkpKQ0KYGBgDQojIFNwZW50IDE3NzMuMDAJIG9uIG9ubGluZSBhZHZlcnRpc2luZw0KDQpgYGB7cn0NCmVscmljaF9leHBlbnNlc18yMDIyX2NsZWFuZWQgJT4lDQpncm91cF9ieShleHBlbnNlX2NhdGVnb3J5KSAlPiUNCnN1bW1hcml6ZSh0b3RhbF9jYXRlZ29yeSA9IHN1bShhbW91bnQpKSAlPiUNCmFycmFuZ2UoZGVzYyh0b3RhbF9jYXRlZ29yeSkpDQpgYGANCkVscmljaCBzcGVudCAkNTI4MzkzLjI5IG9uIG1lZGlhIHdoaWNoIGlzIHNpZ25pZmljYW50bHkgbGVzcyB0aGFuIEJsYWlyDQoNCmBgYHtyfQ0KZWxyaWNoX2V4cGVuc2VzXzIwMjJfY2xlYW5lZCAlPiUNCmZpbHRlcihleHBlbnNlX2NhdGVnb3J5ID09ICJNZWRpYSIpICU+JQ0KZ3JvdXBfYnkoZXhwZW5zZV9wdXJwb3NlKSAlPiUNCnN1bW1hcml6ZSh0b3RhbF9jYXRlZ29yeSA9IHN1bShhbW91bnQpKSAlPiUNCmFycmFuZ2UoZGVzYyh0b3RhbF9jYXRlZ29yeSkpDQpgYGANCg0KI0VscmljaCBzcGVudCAzMksgb24gY29uc3VsdGluZyBmZWVzLg0KDQpUaGlzIGlzIHdoYXQgSSB3cm90ZSBmb3IgTm8uIDUgIlRoZXJlIGFyZSBzaWduaWZhbnQgZGlmZmVyZW5jZXMgaW4gc3BlbmRpbmcgYmV0d2VlbiBFbHJpY2ggYW5kIEJsYWlyIGhlcmUgYW5kIGl0IHNob3dzIGhvdyB0aGUgY2FwaXRhbCBvbiBoYW5kIGNhbiByZWFsbHkgaW5mbHVlbmNlIHRoZSBtZWFucyBhIGNhbmRpZGF0ZSBoYXMgdG8gd2luIG9yIGxvc2UgYSByYWNlLiBFbHJpY2ggaW4gMjAyMiB3ZW50IGFsbC1pbiBvbiBUViBzcGVuZGluZy4gQmxhaXIgc3BlbnQgYSBsb3QgbW9yZSBpbiAyMDE4IGFzIHdlbGwuIg==